iT邦幫忙

2022 iThome 鐵人賽

DAY 27
0
Modern Web

Fastify 101系列 第 27

[Fastify] Day27 - 網站整合 Keycloak 登入 (fastify-keycloak-adapter)

  • 分享至 

  • xImage
  •  

大家好,我是 Yubin

本篇文章會介紹什麼是 Keycloak,一步一步在本地端把 Keycloak 伺服器打起來,並使用 fastify-keycloak-adapter 讓我們的前後端整合的網頁應用程式整合 Keycloak 登入。


前情提要

我們現在有一個前後端整合的 Fastify 專案,但因為沒有實作登入等認證機制,所以任何人都可以瀏覽我們的頁面,戳我們的 API。

但我想讓我的網站,只有我的會員可以瀏覽,只有我的會員可以跟我拿取資源。

那你需要實作一個使用者資料庫、認證機制、登入畫面、登出功能以及使用者的 Session 管理系統 (總不能讓使用者登入一次就一輩子不用再登入)。

聽起來很麻煩,事實上真的很麻煩,而且一個設計不好可能造成嚴重的資安危害,所以我們需要一個專業的解決方案,這裡我們使用 Keycloak。

Keycloak

Keycloak 是 Red Hat 公司在 JBoss 社群維護的一個開源專案。

是一個使用者身份及 Session 管理的解決方案。

GitHub 專案在這裡 https://github.com/keycloak/keycloak

會使用 Keycloak 作為登入伺服器有幾個特點

  • 開源且使用 Apache 授權,可以商用,所以許多公司內部也採用 Keycloak
  • 功能完整,具有友善且易操作的使用者介面
  • 支援單點登入 (Single Sign On)
  • 支援 OAuth2.0,可以進行身份的授權
  • 支援 Open ID,可以利用 idToken 來進行身份的驗證
  • 支援雙因素登入 (2-factor)
  • 支援 LDAP 等使用者資料庫
  • 官方維護多種主流語言的 adapter

還有一個點是,可以快速的在本地端設定使用者資料庫,方便程式的開發。

Keycloak 環境架設與設定

我們現在要先把一個 Keycloak Server 在本機起起來,可以去 Keycloak 官網下載最新版本的 Server 執行檔,或是更快速的,使用 Container。

打開 terminal 敲入:

docker run -d -p 8080:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin jboss/keycloak

使用的 image 是 jboss/keycloak

-p 8080:8080 這個 image 預設會把服務開在 8080 port,我們用本機的 8080 去 mapping 他
-e KEYCLOAK_USER=admin 設定 Keycloak Server 的管理員登入帳號
-e KEYCLOAK_PASSWORD=admin 設定 Keycloak Server 的管理員登入密碼

等 container 啟動好,就可以打開瀏覽器,網址列輸入 localhost:8080

https://ithelp.ithome.com.tw/upload/images/20221012/20151148Ikb7BbreDf.jpg

就可以看到 Keycloak Server 的預設頁面,接著點擊 Administration Console 進入管理頁面。

進入管理頁面前,會跳轉到 Keycloak 登入畫面。

https://ithelp.ithome.com.tw/upload/images/20221012/20151148REnKMAbugf.jpg

在啟動 Container 的時候我有帶 KEYCLOAK_USERKEYCLOAK_PASSWORD 的環境變數,所以我知道管理者帳號密碼都是 admin/admin

這邊要注意,預設情況下沒有管理者帳號是無法登入管理頁面的。

登入之後可以看到如下畫面。

https://ithelp.ithome.com.tw/upload/images/20221012/20151148VsRc9js7wS.jpg

Realm

Realm 在 Keycloak 裡面可以想成 namespace 的意思,每個 Realm 記錄著不同的使用者,Realm 之間彼此是獨立的。

預設會有一個 master 的 Realm。

我們點擊 Add realm 新增一個 Realm: demo

https://ithelp.ithome.com.tw/upload/images/20221012/201511485h4NYIYwCi.jpg

https://ithelp.ithome.com.tw/upload/images/20221012/20151148YKv1bnTxo2.jpg

按下 Create 之後就建立好我們的 realm。


Users

左側點擊 Users 進入使用者的頁面。

User 表示人,某個人要操作系統,以 OAuth2.0 的術語來說是就是資源擁有者
預設狀態下,User 會需要透過輸入帳號密碼的方式進行登入,我們先來建立這個 demo realm 底下的使用者。

https://ithelp.ithome.com.tw/upload/images/20221012/20151148gA2ZhuKzf7.jpg

點擊 Add user 後,填入要新增的使用者。

https://ithelp.ithome.com.tw/upload/images/20221012/20151148zDX2mCkupJ.jpg

這邊新增使用者 user01,除了 username 其他欄位都可以留空。

接著點擊 Credentials 頁簽,來設定這個使用者的密碼。

https://ithelp.ithome.com.tw/upload/images/20221012/20151148U5u0bYtzUw.jpg

這邊方便測試,弄個好記的。

Temporary 選項如果勾選,表示使用者第一次登入後要自行改密碼,預設是勾選狀態。
這邊只是想測試,所以把它關掉。

接著按 Save Passowrd 儲存。

建立好使用者後,我們來設定哪些服務可以來使用我們 Keycloak。


Client

Keycloak 裡面的 Client,可以想成來使用 Keycloak 的服務。

不是每個網站都可以使用我這個 Keycloak 服務,而是要透過特定的 Client,Client 上會有紀錄一些識別用的資訊,經過認證才能使用。

例如,我要登入 A 網站,A 網站帶著某個 Client 的資訊,把我導向 Keycloak 的登入畫面,我登入成功後 Keycloak 把我導回 A 網站。

這邊的 Client 是要事先被建立的,而且上頭要表明 A 網站是合法 (Valid) 的網站,A 網站才能使用這座 Keycloak Server 提供的服務。

Create Client

我們來新增一個 Client,左側點擊 Clients 進入 Client 頁面,再點擊 Create

https://ithelp.ithome.com.tw/upload/images/20221012/20151148NCaVgoKJhO.jpg

輸入 Client ID,這邊使用 client01

https://ithelp.ithome.com.tw/upload/images/20221012/20151148flunMhXkyd.jpg

Access Type

接著我們把 Access Type 設定為 Confidential,要使用 client secret 來初始化登入協議。

https://ithelp.ithome.com.tw/upload/images/20221012/201511480nB8EE2pu6.jpg

Access Type 的解釋 (從網站說明複製的)

  • Confidential clients require a secret to initiate login protocol.
  • Public clients do not require a secret.
  • Bearer-only clients are web services that never initiate a login.

Valid Redirect URIs

如前面提到的,不是每個網站都可以使用這座 Keycloak Server 的服務,必須登記在這裡。

https://ithelp.ithome.com.tw/upload/images/20221012/20151148aFJ83w79dH.jpg

目前只是在本機開發測試,所以填入 http://localhost:8888/*,如果是部屬出去的服務,就要填寫該服務的 Domain Name。

接著按 Save 儲存。

Credentials

接著點擊 Credentials 頁籤,可以看到我們這個 Client 專屬的 Secret。

https://ithelp.ithome.com.tw/upload/images/20221012/20151148QDsoYUhXLG.jpg

把 Secret 複製起來備用。


Keycloak Server 的設定到此告一段落,我們建立了一個 Realm 叫做 demo,建立了一個 Client 叫做 client01,也在這個 Realm 底下建立了一個使用者 user01

容易搞混的是,User 是跟著 Realm,不是跟著 Client。
一個 Realm 可以有多個 User 與多個 Client,跟其他 Realm 彼此獨立。


fastify-keycloak-adapter

現在 Keycloak Server 準備好了,我們要讓我們的程式可以支援 Keycloak。

手上沒有 Fastify 前後端整合專案的朋友,可以參考這篇 Fastify101: 前後端整合 React and Fastify-Static ,跟著文章步驟產生,或參考文章最底下的範例專案。

fastify-keycloak-adapter 是一個 Fastify Plugin,可以快速的介接 Keycloak 的服務。

如果使用者沒有認證資訊或認證資訊過期,會讓使用者跳轉到 Keycloak 登入頁面。使用者登入完會再跳轉回我們的網站,跳轉回來後就可以拿到使用者的身份資訊。

Install

透過 npm 安裝:

npm i fastify-keycloak-adapter

Register

透過 server.register() 進行註冊,並帶入 KeycloakOptions。

import fastify, { FastifyInstance } from 'fastify'
import keycloak, { KeycloakOptions } from 'fastify-keycloak-adapter'

const server: FastifyInstance = fastify()

const opts: KeycloakOptions = {
    appOrigin: 'http://localhost:8888',
    keycloakSubdomain: 'localhost:8080/auth/realms/demo',
    clientId: 'client01',
    clientSecret: 'O9uEfbDHxXgpqET7RVzWnXHE6ecSlR7F'
}

server.register(keycloak, opts)

KeycloakOptions

  • appOrigin 輸入你的網站首頁的 url,記得必須登記在 Client 的 Valid Redirect URLs 清單中。
  • keycloakSubdomain 要連的那座 Keycloak Server 及使用 realm 的位址,localhost:8080 是 Keycloak Server 的 domain,demo 是我們要使用的 Realm。
  • clientId,要使用 Client 的 Client ID。
  • clientSecret,要使用 Client 的 Client Secret。(請從自己的管理頁面複製,你的不會跟我一樣)

更多 KeycloakOptions 的可用選項,請參考官方 GitHub 文件

設定好上述資訊後,我們的 App 就整合好 Keycloak 的服務了!


接著把前端專案 build 好,後端專案 build 好起起來。

打開瀏覽器,網址輸入 localhost:8888

https://ithelp.ithome.com.tw/upload/images/20221012/20151148ZYZvLPZFdR.jpg

原本可以直接瀏覽到前端畫面,現在被跳轉到 Keycloak 的登入頁面。

https://ithelp.ithome.com.tw/upload/images/20221012/201511481FNyn6dQi0.jpg

輸入剛剛我們建立的 user01 的帳號密碼。

登入成功後,會跳轉回我們的網站。

https://ithelp.ithome.com.tw/upload/images/20221012/20151148Vhhc7rolx1.jpg

到這裡就完成 Fastify 前後端整合專案介接 Keycloak 的服務。


本篇文章介紹了 Keycloak 是什麼,以及 Step by Step 的帶大家走過 Keycloak 測試伺服器的架設與設定。

再利用 fastify-keycloak-adapter 這個 Plugin 快速的讓 Fastify App 可以介接 Keycloak 的服務。

更多 Plugin 的使用,像是怎麼在程式中拿到使用者的資訊、如何讓使用者登出,等等,可以參考官方的文件
這個 Plugin 目前是我在維護,有任何問題或建議都可以直接丟 issue 或丟 PR 給我 XD

以上完整的專案範例可以參考 GitHub


篇幅有點長,感謝收看。


上一篇
[Fastify] Day26 - 前後端整合 React and Fastify-Static
下一篇
[Fastify] Day28 - Containerization (Dockerfile)
系列文
Fastify 10130
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
Brandy
iT邦新手 2 級 ‧ 2022-10-13 08:15:03

fastify-keycloak-adapter 好用!

我要留言

立即登入留言